package com.gitee.cliveyuan.tools.http;


import com.gitee.cliveyuan.tools.StringTools;
import com.gitee.cliveyuan.tools.exception.NetException;
import com.google.common.collect.Maps;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;

import java.util.Map;
import java.util.Objects;

/**
 * Created by clive at 2018/11/26.
 */
public abstract class AbstractHttpRequest {

    String url;
    Map<String, String> params = Maps.newHashMap();
    Map<String, String> headers = Maps.newHashMap();
    Map<String, String> cookies = Maps.newHashMap();
    int timeout;
    boolean addDefaultHeaders;

    /**
     * 设置请求url地址
     *
     * @param url http or https 请求地址
     */
    public AbstractHttpRequest url(String url) {
        this.url = url;
        return this;
    }

    /**
     * 设置请求入参, 如果是get请求时此入参将拼接到url后
     *
     * @param params 入参map
     */
    public AbstractHttpRequest params(Map<String, String> params) {
        this.params = params;
        return this;
    }

    /**
     * 通过字符串设置请求入参, 如果是get请求时此入参将拼接到url后
     * 格式:
     * <pre>
     *     user: clive
     *     pwd:  123456
     * </pre>
     * 每行一对,每对之间用分号分隔对应key-value
     * 会去除前后空格
     *
     * @param kv
     */
    public AbstractHttpRequest params(String kv) {
        this.params = InnerTools.keyValueStrToMap(kv);
        return this;
    }

    /**
     * 添加入参
     *
     * @param key
     * @param value
     */
    public AbstractHttpRequest addParam(String key, String value) {
        this.params.put(key, value);
        return this;
    }

    /**
     * 设置请求头信息
     *
     * @param headers
     */
    public AbstractHttpRequest headers(Map<String, String> headers) {
        this.headers = headers;
        return this;
    }

    /**
     * 设置请求头信息
     * 格式:
     * <pre>
     *     token: 123456
     *     uid:   111111
     * </pre>
     * 每行一对,每对之间用分号分隔对应key-value
     * 会去除前后空格
     *
     * @param kv
     */
    public AbstractHttpRequest headers(String kv) {
        this.headers = InnerTools.keyValueStrToMap(kv);
        return this;
    }

    /**
     * 添加请求头
     *
     * @param key
     * @param value
     */
    public AbstractHttpRequest addHeader(String key, String value) {
        this.headers.put(key, value);
        return this;
    }

    /**
     * 设置cookie信息
     *
     * @param cookies
     */
    public AbstractHttpRequest cookies(Map<String, String> cookies) {
        this.cookies = cookies;
        return this;
    }

    /**
     * 设置cookie信息
     * <p>
     * 格式:
     * <pre>
     *     JSESSIONID: 01010101010101010
     *     _uid:   111111
     * </pre>
     * 每行一对,每对之间用分号分隔对应key-value
     * 会去除前后空格
     *
     * @param kv
     */
    public AbstractHttpRequest cookies(String kv) {
        this.cookies = InnerTools.keyValueStrToMap(kv);
        return this;
    }

    /**
     * 添加cookie信息
     *
     * @param key
     * @param value
     */
    public AbstractHttpRequest addCookie(String key, String value) {
        this.cookies.put(key, value);
        return this;
    }

    /**
     * 超时时间
     * 单位:毫秒, 默认:30000
     *
     * @param timeout
     */
    public AbstractHttpRequest timeout(int timeout) {
        this.timeout = timeout;
        return this;
    }

    /**
     * 添加默认的请求头
     *
     */
    public AbstractHttpRequest addDefaultHeaders() {
        this.addDefaultHeaders = true;
        return this;
    }

    /**
     * 发送get请求
     *
     * @return 响应内容
     * @throws NetException
     */
    public abstract String get() throws NetException;

    /**
     * 发送post请求
     *
     * @return 响应内容
     * @throws NetException
     */
    public abstract String post() throws NetException;

    /**
     * 执行get请求
     *
     * @return 返回响应数据
     * @throws NetException
     */
    public abstract HttpResp executeGet() throws NetException;

    /**
     * 执行post请求
     *
     * @return 返回响应数据
     * @throws NetException
     */
    public abstract HttpResp executePost() throws NetException;


    /**
     * 发送get请求,并将结果转为Jsoup的Document
     *
     * @throws NetException
     */
    public Document getByDocument() throws NetException {
        return Jsoup.parse(get());
    }

    /**
     * 发送post请求,并将结果转为Jsoup的Document
     *
     * @throws NetException
     */
    public Document postByDocument() throws NetException {
        return Jsoup.parse(post());
    }

    void validate() throws NetException {
        String url = this.url;
        if (StringTools.isBlank(url)) {
            throw NetException.illegalInvokeError("url is required");
        }
        url = url.toLowerCase();
        if (!url.startsWith("http://") && !url.startsWith("https://")) {
            throw NetException.illegalInvokeError("url should start with http(s)://");
        }
    }
}
